﻿using UnityEditor;
using UnityEngine;
using System.IO;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using UnityEditor.Callbacks;

namespace MagicLib
{
    public class CreateComponentCode : ScriptableWizard
    {

        private const string PENDING_COMPONENTS_KEY = "MagicLib_PendingComponents";
        private const string DEFAULT_PATH = "Assets/";

        [SerializeField] private string componentName = "NewComponent";
        [SerializeField] private string path = DEFAULT_PATH;
        // 手动输入的路径
        [SerializeField] private string customSavePath = "";

        private GameObject targetObject;
        private bool selectionValid;

        private static bool isInitialized = false;

        private static CreateComponentCode currentWindow = null;

        [MenuItem("MagicLib/CreateComponentCode %#x", priority = 13)]
        public static void ToggleWindow()
        {
            // 如果窗口存在且未关闭，则关闭它
            if (currentWindow != null)
            {
                currentWindow.Close();
                currentWindow = null;
                return;
            }

            // 否则创建新窗口
            CreateWindow();
        }

        // 创建窗口并初始化事件监听器
        private static void CreateWindow()
        {
            try
            {
                currentWindow = DisplayWizard<CreateComponentCode>("快速创建脚本", "创建");
                if (currentWindow != null)
                {
                    currentWindow.maxSize = new Vector2(300, 190);
                    currentWindow.minSize = new Vector2(100, 190);
                    // 恢复保存的路径
                    currentWindow.customSavePath = EditorPrefs.GetString("CachPath", "");

                    // 自动设置脚本名称为选中物体名称
                    if (Selection.activeGameObject != null)
                    {
                        currentWindow.componentName = Selection.activeGameObject.name;
                    }
                }

                // 初始化一次性事件
                if (!isInitialized)
                {
                    EditorApplication.update += InitializeOnce;
                    EditorApplication.quitting += () =>
                    {
                        isInitialized = false;
                        EditorApplication.update -= InitializeOnce;
                    };
                    isInitialized = true;
                }
            }
            catch (Exception e)
            {
                Debug.LogError($"脚本创建失败: {e}");
                currentWindow = null;
                isInitialized = false;
                EditorApplication.update -= InitializeOnce;
                throw;
            }
        }

        // 注册快捷键监听器，但不立即初始化事件
        [InitializeOnLoadMethod]
        private static void RegisterShortcutMonitor()
        {
            EditorApplication.update += () =>
            {
                if (Event.current != null && Event.current.type == EventType.KeyDown
                    && Event.current.keyCode == KeyCode.X
                    && (Event.current.control || Event.current.command)
                    && Event.current.shift)
                {
                    CreateWindow();
                    Event.current.Use();
                }
            };
        }

        // 初始化事件，只在第一次运行时调用一次
        private static void InitializeOnce()
        {
            // 确保只初始化一次
            EditorApplication.update -= InitializeOnce;
            // 确保快捷键注册成功
            EditorApplication.delayCall += () =>
            {
                Menu.SetChecked("MagicLib/CreateComponentCode &x", false);
            };
        }

        // 更新选择状态
        private void OnEnable()
        {
            // 注册选择变化事件
            Selection.selectionChanged += UpdateSelection;
            // 初始化时也更新名称
            if (Selection.activeGameObject != null)
            {
                componentName = SanitizeClassName(Selection.activeGameObject.name);
            }
            UpdateSelection();
        }

        // 更新选择状态
        private void OnDisable()
        {
            // 取消注册选择变化事件
            Selection.selectionChanged -= UpdateSelection;
            // 确保清理静态状态
            isInitialized = false;
        }

        // 更新选择状态
        protected override bool DrawWizardGUI()
        {
            // 绘制控件
            EditorGUI.BeginChangeCheck();
            {
                EditorGUILayout.Space(10);
                componentName = EditorGUILayout.TextField("类名:", SanitizeClassName(componentName));
                // 单独检查路径输入变化
                EditorGUILayout.BeginHorizontal();
                {
                    // 使用DelayedTextField并设置控件名以便获取焦点状态
                    GUI.SetNextControlName("pathField");
                    string newPath = EditorGUILayout.DelayedTextField("存储路径:",
                        !string.IsNullOrEmpty(customSavePath) ? customSavePath :
                        (EditorPrefs.GetString("CachPath") ?? path));

                    // 只在用户完成输入时处理路径
                    if (!string.IsNullOrEmpty(newPath) && newPath.StartsWith("Assets/"))
                    {
                        // 统一处理路径格式并立即保存
                        customSavePath = newPath.Trim();
                        if (!customSavePath.EndsWith("/")) customSavePath += "/";
                        // 立即保存到EditorPrefs，不等待Create按钮
                        EditorPrefs.SetString("CachPath", customSavePath);
                    }

                    // 浏览按钮
                    if (GUILayout.Button("...", GUILayout.Width(20)))
                    {
                        string selectedPath = EditorUtility.OpenFolderPanel("Select Save Folder",
                            !string.IsNullOrEmpty(customSavePath) ? customSavePath : path, "");

                        if (!string.IsNullOrEmpty(selectedPath))
                        {
                            if (selectedPath.StartsWith(Application.dataPath))
                            {
                                customSavePath = "Assets" + selectedPath.Substring(Application.dataPath.Length);
                                if (!customSavePath.EndsWith("/")) customSavePath += "/";
                                EditorPrefs.SetString("CachPath", customSavePath);
                            }
                        }
                    }
                }
                EditorGUILayout.EndHorizontal();
            }

            DisplaySelectionStatus();
            return EditorGUI.EndChangeCheck(); ;
        }

        // Create按钮被点击时调用，执行脚本创建逻辑
        private void OnWizardCreate()
        {
            // 验证输入是否有效
            if (!ValidateInputs()) return;

            // 获取当前路径输入框的值
            string currentPath = customSavePath;

            // 处理路径格式并保存
            if (!string.IsNullOrEmpty(currentPath))
            {
                currentPath = currentPath.Trim();
                if (!currentPath.EndsWith("/")) currentPath += "/";
                if (currentPath.StartsWith("Assets/"))
                {
                    customSavePath = currentPath;
                    EditorPrefs.SetString("CachPath", currentPath);
                }
            }
            else
            {
                // 如果没有自定义路径，使用默认路径
                string pathToSave = path.Trim();
                if (!pathToSave.EndsWith("/")) pathToSave += "/";
                EditorPrefs.SetString("CachPath", pathToSave);
            }

            string className = SanitizeClassName(componentName);
            string fullPath = GetScriptPath(className);

            // 创建脚本文件并添加组件到选中物体
            try
            {
                CreateScriptAsset(className, fullPath);

                // 只有选中物体时才添加组件
                if (targetObject != null)
                {
                    AddPendingComponent(className, targetObject);
                }

                // 保存当前路径状态
                if (!string.IsNullOrEmpty(customSavePath))
                {
                    EditorPrefs.SetString("CachPath", customSavePath);
                }

            }
            catch (Exception e)
            {
                Debug.LogError($"Script creation failed: {e.Message}\n{e.StackTrace}");
                EditorUtility.DisplayDialog("Error",
                    $"Script creation failed: {e.Message}", "OK");
            }

            // 确保窗口正确关闭
            EditorApplication.delayCall += () =>
            {
                Close();
                currentWindow = null;
            };
        }

        // 验证输入是否有效（名称与路径都要满足才能生产脚本文件）
        private bool ValidateInputs()
        {
            // 检查选择是否有效（选中多个物体时无效）
            if (!selectionValid)
            {
                EditorUtility.DisplayDialog("Error",
                    "Please select a single GameObject in the scene", "OK");
                return false;
            }
            // 检查脚本名称是否为空或空白
            if (string.IsNullOrWhiteSpace(componentName))
            {
                EditorUtility.DisplayDialog("Error",
                    "Script name cannot be empty", "OK");
                return false;
            }
            // 检查路径是否以"Assets/"开头
            if (!path.StartsWith("Assets/"))
            {
                EditorUtility.DisplayDialog("Error",
                    "Path must be within the Assets folder", "OK");
                return false;
            }

            // 检查路径有效性
            try { Path.GetFullPath(path); }
            catch
            {
                EditorUtility.DisplayDialog("Error",
                    "Invalid file path", "OK");
                return false;
            }

            return true;
        }


        // 重名文件检查 -> 弹窗是否覆盖 -> 生成脚本文件 -> 刷新资源数据库 -> 设置脏状态
        private void CreateScriptAsset(string className, string fullPath)
        {
            // 防止覆盖现有文件
            if (File.Exists(fullPath))
            {
                if (!EditorUtility.DisplayDialog("Warning",
                    $"File {className}.cs already exists. Overwrite?", "Yes", "No"))
                {
                    // throw new OperationCanceledException("User canceled overwrite");
                }
            }

            string scriptContent = $@"using UnityEngine;

public class {className} : MonoBehaviour
{{
    private void Start()
    {{
        
    }}

    private void Update()
    {{

    }}
}}";

            // 确保目录存在
            Directory.CreateDirectory(Path.GetDirectoryName(fullPath));

            // 使用临时文件确保原子性写入
            string tempPath = fullPath + ".tmp";
            File.WriteAllText(tempPath, scriptContent);

            try
            {
                // 确保文件写入完成
                FileStream tempStream = File.Open(tempPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None);
                tempStream.Close();

                // 重命名操作
                if (File.Exists(fullPath)) File.Delete(fullPath);
                File.Move(tempPath, fullPath);

                // 延迟异步刷新避免UI事件冲突
                EditorApplication.delayCall += () =>
                {
                    try
                    {
                        // 验证文件状态
                        if (!File.Exists(fullPath))
                        {
                            Debug.LogError($"目标文件不存在: {fullPath}");
                            return;
                        }

                        // 分阶段刷新
                        AssetDatabase.ImportAsset(fullPath, ImportAssetOptions.ForceUpdate);
                        EditorUtility.SetDirty(AssetDatabase.LoadMainAssetAtPath(fullPath));

                        // 完整刷新
                        AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport);
                        AssetDatabase.SaveAssets();
                    }
                    catch (Exception e)
                    {
                        Debug.LogError($"异步刷新失败: {e.Message}");
                    }
                };
            }
            catch (Exception e)
            {
                Debug.LogError($"文件操作失败: {e.Message}");
                throw;
            }
            finally
            {
                // 清理临时文件
                if (File.Exists(tempPath)) File.Delete(tempPath);
            }
        }

        // 添加待处理组件到持久化存储中
        private void AddPendingComponent(string className, GameObject target)
        {
            var pending = GetPendingComponents();
            pending.Add(new PendingComponent
            {
                guid = Guid.NewGuid().ToString(),
                className = className,
                gameObjectInstanceID = target.GetInstanceID() // 使用InstanceID代替路径
            });
            SavePendingComponents(pending);
        }

        // 更新选中物体状态并刷新界面
        private void UpdateSelection()
        {
            selectionValid = Selection.gameObjects.Length <= 1;
            targetObject = Selection.gameObjects.Length == 1 ? Selection.activeGameObject : null;

            // 选中物体变化时自动更新Script Name
            if (targetObject != null && !string.IsNullOrEmpty(targetObject.name))
            {
                componentName = SanitizeClassName(targetObject.name);
            }

            // 刷新界面
            Repaint();
        }

        // 显示选中物体状态信息
        private void DisplaySelectionStatus()
        {
            EditorGUILayout.Space(5);

            if (!selectionValid)
            {
                EditorGUILayout.HelpBox("多目标物体将不被支持",
                    MessageType.Error);
            }
            else
            {
                using (new EditorGUILayout.HorizontalScope())
                {
                    GUILayout.Label("目标物体:", GUILayout.Width(120));
                    EditorGUILayout.ObjectField(targetObject, typeof(GameObject), true);
                }
            }
        }

        // 获取脚本保存路径，处理自定义和默认情况
        private string GetScriptPath(string className)
        {
            string basePath = !string.IsNullOrEmpty(customSavePath) ? customSavePath : path;
            // 确保路径以/结尾
            if (!basePath.EndsWith("/")) basePath += "/";
            return Path.Combine(basePath, $"{className}.cs").Replace("\\", "/");
        }

        // 清理文件名非法字符，确保其为有效C#类名
        private static string SanitizeClassName(string input)
        {
            if (string.IsNullOrEmpty(input)) return "NewComponent";

            // 移除非字母数字字符，保留Unicode字符
            string sanitized = Regex.Replace(input, @"[^\p{L}\p{N}_]", "");

            // 处理空字符串情况
            if (string.IsNullOrEmpty(sanitized)) return "NewComponent";

            // 确保首字符是字母或下划线
            return char.IsLetter(sanitized[0]) || sanitized[0] == '_' ?
                sanitized : "_" + sanitized;
        }

        // 持久化待处理组件结构，用于脚本重载后恢复添加操作
        private static List<PendingComponent> GetPendingComponents()
        {
            string json = EditorPrefs.GetString(PENDING_COMPONENTS_KEY, "[]");
            try
            {
                return JsonUtility.FromJson<SerializableList<PendingComponent>>(json).list
                    ?? new List<PendingComponent>();
            }
            catch
            {
                return new List<PendingComponent>();
            }
        }

        // 持久化待处理组件结构，用于脚本重载后恢复添加操作
        private static void SavePendingComponents(List<PendingComponent> pending)
        {
            var wrapper = new SerializableList<PendingComponent> { list = pending };
            EditorPrefs.SetString(PENDING_COMPONENTS_KEY, JsonUtility.ToJson(wrapper));
        }

        // 脚本重载时处理待添加组件
        [DidReloadScripts]
        private static void OnScriptsReloaded()
        {
            var pending = GetPendingComponents();
            if (pending.Count == 0) return;

            var remaining = new List<PendingComponent>();
            bool componentsAdded = false;

            foreach (var item in pending)
            {
                if (TryAddComponent(item))
                {
                    componentsAdded = true;
                }
                else
                {
                    remaining.Add(item);
                }
            }

            SavePendingComponents(remaining);

            if (componentsAdded)
            {
                EditorApplication.delayCall += () =>
                {
                    AssetDatabase.Refresh();
                    SceneView.RepaintAll();
                };
            }
        }

        // 尝试添加组件，返回是否成功
        private static bool TryAddComponent(PendingComponent pending)
        {
            // 通过InstanceID查找游戏对象
            GameObject target = EditorUtility.InstanceIDToObject(pending.gameObjectInstanceID) as GameObject;
            if (target == null) return false;

            // 在已加载的程序集中查找类型
            Type componentType = Type.GetType(pending.className) ??
                AppDomain.CurrentDomain.GetAssemblies()
                    .SelectMany(a => a.GetTypes())
                    .FirstOrDefault(t => t.Name == pending.className &&
                         t.IsSubclassOf(typeof(MonoBehaviour)));

            if (componentType == null) return false;

            // 防止重复添加组件
            if (target.GetComponent(componentType) == null)
            {
                Undo.RecordObject(target, $"Add {pending.className}");
                target.AddComponent(componentType);
                EditorUtility.SetDirty(target);
            }

            return true;
        }

        // 待处理组件结构，用于脚本重载后恢复添加操作
        [Serializable]
        private struct PendingComponent
        {
            public string guid;
            public string className;
            public int gameObjectInstanceID; // 使用InstanceID更可靠
        }

        // 序列化列表结构，用于JSON转换
        [Serializable]
        private class SerializableList<T>
        {
            public List<T> list;
        }

    }
}